#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>

#include "tablero.h"

struct tablero
{
  int tamanio;
  contenidoT** tablero;
};

static void liberarTablero(contenidoT** tablero, int tamanio);

tableroT
newTablero(char filename[])
{
  tableroT tablero;
  int i=0, archivo=0, filas=0, columnas=0, columnas_antes=0, aux_leido=1;
  contenidoT celda[MAX_TAMANIO+0];

  archivo = open(filename, O_RDONLY);
  if(archivo < 0)
  {
    return NULL;
  }

  //estructura del tablero
  printDebug("Aloco tablero");
  tablero = calloc(sizeof(struct tablero),1);
  if(tablero == NULL)
  {
    printDebug("Error de memoria");
    return NULL;
  }
  //aloco maximo tamanio de filas
  printDebug("Aloco filas");
  tablero->tablero = calloc(MAX_TAMANIO*sizeof(contenidoT*),1);
  if(tablero->tablero == NULL)
  {
    printDebug("Error de memoria2");
    return NULL;
  }
  //aloco maximo tamanio de columnas
  for(i=0; i<MAX_TAMANIO; i++)
  {
    printDebug("Aloco columna %d", i);
    tablero->tablero[i] = calloc(MAX_TAMANIO*sizeof(contenidoT),1);
    if(tablero->tablero[i] == NULL)
    {
      printDebug("Error de memoria3");
      liberarTablero(tablero->tablero, i-1);
      free(tablero);
      return NULL;
    }
  }

  //leo el archivo y cargo el tablero
  while(aux_leido > 0)
  {
    aux_leido = read(archivo, &((tablero->tablero)[filas][columnas]), sizeof(contenidoT));
    if(aux_leido < 0)
    {
      printDebug("Errno: %s", strerror(errno));
      printDebug("Error en el archivo1");
      liberarTablero(tablero->tablero, MAX_TAMANIO);
      free(tablero);
      return NULL;
    }
    else if(aux_leido == 0)
    {
      filas++;
      break;
    }
    printDebug("celda = %c", tablero->tablero[filas][columnas]);

    if(tablero->tablero[filas][columnas] == '\n')
    {
      printDebug("columnas_antes = %d", columnas_antes);
      printDebug("columnas = %d", columnas);
      printDebug("filas = %d", filas);
      //valido cantidad de columnas entre filas (excepto primera)
      if(columnas_antes!=columnas && filas!=0)
      {
        printDebug("Error en el archivo3");
        liberarTablero(tablero->tablero, MAX_TAMANIO);
        free(tablero);
        return NULL;
      }
      else
      {
        columnas_antes = columnas;
        columnas = 0;
      }
      filas++;
      //valido no pasarme de tamanio, la matriz debe ser cuadrada
      if(filas > columnas_antes)
      {
        printDebug("Error en el archivo4");
        liberarTablero(tablero->tablero, MAX_TAMANIO);
        free(tablero);
        return NULL;
      }
    }
    else //celda[columnas]!=\n
    {
      columnas++;
    }
  }

  printDebug("Archivo leido (%d x %d)", filas, columnas);
  if(filas != columnas)
  {
    printDebug("Error en el archivo5");
    liberarTablero(tablero->tablero, MAX_TAMANIO);
    free(tablero);
    return NULL;
  }

  //ajustar el tablero segun el tamanio leido (no valido porque siempre es a menor tamanio
  tablero->tablero = realloc(tablero->tablero, filas*sizeof(contenidoT*));
  for(i=0; i<filas; i++)
  {
    tablero->tablero[i] = realloc(tablero->tablero[i], filas*sizeof(contenidoT));
  }
  tablero->tamanio = filas;

  close(archivo);

  return tablero;
}

void
freeTablero(tableroT tablero)
{
  if(tablero != NULL)
  {
    liberarTablero(tablero->tablero, tablero->tamanio);
    free(tablero);
  }
}

static void
liberarTablero(contenidoT** tablero, int tamanio)
{
  int i;

  if(tablero != NULL)
  {
    for(i=0; i<tamanio; i++)
    {
      if(tablero[i] != NULL)
      {
        free(tablero[i]);
      }
    }
    free(tablero);
  }
}
